package com.erytech.linktalk.web.client.datasource;

import com.erytech.linktalk.web.client.framework.DataSource;
import com.erytech.linktalk.web.client.service.EndpointUtil;
import com.erytech.linktalk.web.client.service.UserInfo;
import com.erytech.linktalk.web.client.service.UserRpcService;
import com.erytech.linktalk.web.client.service.UserRpcServiceAsync;
import com.google.gwt.core.client.GWT;
import com.google.gwt.user.client.Timer;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.rpc.InvocationException;
import com.google.gwt.user.client.rpc.ServiceDefTarget;

public class UserDataSource extends DataSource {

	private Timer timer;
	
	private UserInfo userInfo;
	
	private String saidTo = UserInfo.ALL;
	
	private UserRpcServiceAsync userRpc;

	private RoomDataSource roomDataSource;

	public UserDataSource(RoomDataSource roomDataSource) {
		this.roomDataSource = roomDataSource;
	}
	
	public RoomDataSource getRoomDataSource() {
		return roomDataSource;
	}

	public boolean isLogin() {
		return userInfo != null;
	}
	
	public UserInfo getUserInfo() {
		return userInfo;
	}

	public String getSaidTo() {
		return saidTo;
	}

	public void saidTo(String userName) {
		if(userInfo != null && userInfo.getName().equals(userName))  {
			return;
		}
		if(saidTo != null && saidTo.equals(userName)) {
			return;
		}
		this.saidTo = userName;
		fireDataUpdateEvent(new UserUpdateEvent(this, UserUpdateEvent.SAID_TO, userName));
	}

	public void startPolling() {
		getTimer().scheduleRepeating(2000);		
	}

	public void stopPolling() {
		getTimer().cancel();
	}
	
	private void setUserInfo(UserInfo userInfo) {
		this.userInfo = userInfo;
	}

	public void login(final UserInfo userInfo) {
		userInfo.setRoomId(getRoomDataSource().getRoomId());
		getUserRpc().login(userInfo, new AsyncCallback() {
			public void onSuccess(Object obj) {
				UserInfo userInfo = (UserInfo)obj;
				setUserInfo(userInfo);
				fireDataUpdateEvent(new UserUpdateEvent(UserDataSource.this, 
						UserUpdateEvent.LOGIN_SUCCESS, new UserInfo[]{userInfo}));
				getRoomDataSource().enterRoom(userInfo);
			}
		
			public void onFailure(Throwable t) {
				fireDataUpdateEvent(new UserUpdateEvent(UserDataSource.this, 
						UserUpdateEvent.LOGIN_FAILURE, t));
				setUserInfo(null);
			}
		});
	}
	
	public void logout() {
		getTimer().cancel();
		getUserRpc().logout(new AsyncCallback() {
			public void onSuccess(Object obj) {
				fireDataUpdateEvent(new UserUpdateEvent(UserDataSource.this, 
						UserUpdateEvent.LOGOUT_SUCCESS));
				getRoomDataSource().leftRoom();
				setUserInfo(null);
			}
			public void onFailure(Throwable t) {
				if(t instanceof InvocationException) {
					//quiet quit
					return;
				}
				fireDataUpdateEvent(new UserUpdateEvent(UserDataSource.this, 
						UserUpdateEvent.LOGOUT_FAILURE));
			}
		});
	}
		
	private void pollUsers() {
		getUserRpc().getUsers(new AsyncCallback() {
			public void onSuccess(Object obj) {
				UserInfo[] users = (UserInfo[]) obj;
				fireDataUpdateEvent(new UserUpdateEvent(UserDataSource.this, 
						UserUpdateEvent.POLL_SUCCESS, users));
			}
			public void onFailure(Throwable t) {
				if(t instanceof InvocationException) {
					getTimer().cancel();
					return;
				}
				fireDataUpdateEvent(new UserUpdateEvent(UserDataSource.this, 
						UserUpdateEvent.POLL_FAILURE, t));
			}
		});
	}

	private Timer getTimer() {
		if(timer == null) {
			timer = new Timer() {
				public void run() {
					pollUsers();
				}
			};
		}
		return timer;
	}
	
	private UserRpcServiceAsync getUserRpc() {
		if (userRpc == null) {
			userRpc = (UserRpcServiceAsync) GWT.create(UserRpcService.class);
			((ServiceDefTarget) userRpc).setServiceEntryPoint(EndpointUtil
					.getRealEndPoint("/user.rpc"));
		}
		return userRpc;
	}

}